﻿using System;
using System.Data;
using System.IO;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

namespace SSISComponents
{
    public partial class frmMain : Form
    {
        private DataSet ds_Checked = new DataSet("Checked");
        private DataTable dt_Shapefile = new DataTable("Shapefile");
        private DataTable dt_dbase = new DataTable("dbase");
        private DataTable AttributeColumns = null;
        private DataTable AttributeColumnsShape = null;
        //private string strFilename = null;
        private ShapeFileReadInfo info;
        private IDTSComponentMetaData100 m_dtsComponentMetadata;
        private IServiceProvider m_serviceProvider; 
        private Variables m_variables;
        private Connections m_connections;
        private string strShapeFileData;
        
        /// <summary>
        /// SetFile and DataSet
        /// </summary>
        /// <param name="th"></param>
        /// <param name="connection"></param>
        public frmMain(IDTSComponentMetaData100 dtsComponentMetadata, IServiceProvider serviceProvider, Variables variables, Connections connections)
        {
            InitializeComponent();
           
            m_dtsComponentMetadata = dtsComponentMetadata;
            m_serviceProvider = serviceProvider;
            m_variables = variables;
            m_connections = connections;
            
            /// Sets each internal var with CustomPropertyCollection data
            try
            {
                if (m_dtsComponentMetadata.CustomPropertyCollection["ShapeFilePath"].Value != null)
                {
                    txtShape.Text = m_dtsComponentMetadata.CustomPropertyCollection["ShapeFilePath"].Value.ToString();
                    this.SetFile(txtShape.Text);
                }
                if (m_dtsComponentMetadata.CustomPropertyCollection["ShapeFileData"].Value != null)
                {
                    this.strShapeFileData = m_dtsComponentMetadata.CustomPropertyCollection["ShapeFileData"].Value.ToString();
                    ds_Checked.ReadXml(new StringReader(strShapeFileData));
                }
                else
                {
                    ds_Checked.Tables.Add(dt_Shapefile);
                    ds_Checked.Tables.Add(dt_dbase);
                }


                if (m_dtsComponentMetadata.CustomPropertyCollection["IgnoreConversionError"].Value != null)
                {
                    if (m_dtsComponentMetadata.CustomPropertyCollection["IgnoreConversionError"].Value.ToString().ToUpper() == "TRUE")
                    {
                        this.cbError.Checked = true;
                    }
                    else 
                    {
                        this.cbError.Checked = false;
                    }
                }

                ///Set the SRID
                if (m_dtsComponentMetadata.CustomPropertyCollection["SRID"].Value != null)
                {
                    txtSRID.Text = m_dtsComponentMetadata.CustomPropertyCollection["SRID"].Value.ToString();
                }

                /// Set the SpatialDataType
                if (m_dtsComponentMetadata.CustomPropertyCollection["SpatialDataType"].Value != null)
                {
                    if (m_dtsComponentMetadata.CustomPropertyCollection["SpatialDataType"].Value.ToString() == "Geography")
                    {
                        rbGeometry.Checked = false;
                        rbGeography.Checked = true;
                    }
                    else
                    {
                        rbGeometry.Checked = true;
                        rbGeography.Checked = false;
                    }
                }
                else
                {
                    rbGeometry.Checked = true;
                    rbGeography.Checked = false;
                }

            }
            catch 
            {
                MessageBox.Show("An error occurred while loading the data...");
            }          
        }

        /// <summary>
        /// open the openfiledialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender, EventArgs e)
        {
         if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
         {
             SetFile(openFileDialog1.FileName.ToString());
         }
        }

        /// <summary>
        /// Set the Shapefile and load different information
        /// </summary>
        /// <param name="Filename"></param>
        private void SetFile(string Filename)
        {
            info = new ShapeFileReadInfo();
            info.FileName = Filename;
            
            txtShape.Text = info.FileName;
            txtDbase.Text = info.dbaseFile;
            AttributeColumns = info.AttributeColumns();

            this.clbDbaseData.DataSource = AttributeColumns;
            this.clbDbaseData.DisplayMember = "Name";
            tabControl2.Enabled = true;
        }

        /// <summary>
        /// Closes the Application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Load Action
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOK_Click(object sender, EventArgs e)
        {

            m_dtsComponentMetadata.CustomPropertyCollection["ShapeFilePath"].Value = txtShape.Text;
            m_dtsComponentMetadata.CustomPropertyCollection["ShapeFileData"].Value = this.GetXML();
            m_dtsComponentMetadata.CustomPropertyCollection["SRID"].Value = Convert.ToInt32(txtSRID.Text);
            m_dtsComponentMetadata.CustomPropertyCollection["IgnoreConversionError"].Value = this.cbError.Checked.ToString();
            if (rbGeography.Checked)
            {
                m_dtsComponentMetadata.CustomPropertyCollection["SpatialDataType"].Value = "Geography";
            }
            else
            {
                m_dtsComponentMetadata.CustomPropertyCollection["SpatialDataType"].Value = "Geometry";
            }
            
            DialogResult = DialogResult.OK;
            
        }

        /// <summary>
        /// Check if string contains ','
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string Check(string value)
        {
            if (value.Substring(0,1) == ",")
            {
                value = "0" + value;
            }
            value = value.Replace(",", ".");
            return value;
        }

        //###################################################
        //Returns a dataset with all checked values as string
        //###################################################
        private string GetXML()
        {
            if (!ds_Checked.Tables.Contains("dbase"))
            {
                ds_Checked.Tables.Add("dbase");
            }
            
            try
            {
                ds_Checked.Tables["dbase"].Rows.Clear();
            }
            catch { }
            
            try
            {
                ds_Checked.Tables["Shapefile"].Rows.Clear();
            }
            catch { }

            if (ds_Checked.Tables["dbase"].Columns.Count != 6) // || dt_dbase.Columns[0].ColumnName.ToString().ToUpper() != "NAME")
            {
                ds_Checked.Tables["dbase"].Columns.Clear();

                DataColumn col_dbase = new DataColumn("Name", System.Type.GetType("System.String"));
                DataColumn colDataType = new DataColumn("DataType", System.Type.GetType("System.String"));
                DataColumn colLength = new DataColumn("Length", System.Type.GetType("System.Int32"));
                DataColumn colPrecision = new DataColumn("Precision", System.Type.GetType("System.Int32"));
                DataColumn colScale = new DataColumn("Scale", System.Type.GetType("System.Int32"));
                DataColumn colCodePage = new DataColumn("CodePage", System.Type.GetType("System.Int32"));

                ds_Checked.Tables["dbase"].Columns.Add(col_dbase);
                ds_Checked.Tables["dbase"].Columns.Add(colDataType);
                ds_Checked.Tables["dbase"].Columns.Add(colLength);
                ds_Checked.Tables["dbase"].Columns.Add(colPrecision);
                ds_Checked.Tables["dbase"].Columns.Add(colScale);
                ds_Checked.Tables["dbase"].Columns.Add(colCodePage);

            }
            if (ds_Checked.Tables["Shapefile"].Columns.Count != 6) // || dt_Shapefile.Columns[0].ColumnName.ToString().ToUpper() != "NAME")
            {
                ds_Checked.Tables["Shapefile"].Columns.Clear();

                DataColumn col_dbase = new DataColumn("Name", System.Type.GetType("System.String"));
                DataColumn colDataType = new DataColumn("DataType", System.Type.GetType("System.String"));
                DataColumn colLength = new DataColumn("Length", System.Type.GetType("System.Int32"));
                DataColumn colPrecision = new DataColumn("Precision", System.Type.GetType("System.Int32"));
                DataColumn colScale = new DataColumn("Scale", System.Type.GetType("System.Int32"));
                DataColumn colCodePage = new DataColumn("CodePage", System.Type.GetType("System.Int32"));

                ds_Checked.Tables["Shapefile"].Columns.Add(col_dbase);
                ds_Checked.Tables["Shapefile"].Columns.Add(colDataType);
                ds_Checked.Tables["Shapefile"].Columns.Add(colLength);
                ds_Checked.Tables["Shapefile"].Columns.Add(colPrecision);
                ds_Checked.Tables["Shapefile"].Columns.Add(colScale);
                ds_Checked.Tables["Shapefile"].Columns.Add(colCodePage);
            }

            foreach (int dbaseChecked in clbDbaseData.CheckedIndices)
            {
                DataRow dr = ds_Checked.Tables["dbase"].NewRow();
                dr[0] = AttributeColumns.Rows[dbaseChecked][0];
                dr[1] = "DataType.DT_WSTR";
                dr[2] = 50;
                dr[3] = 0;
                dr[4] = 0;
                dr[5] = 0;
                ds_Checked.Tables["dbase"].Rows.Add(dr);
            }

            
            foreach (int shapeChecked in clbShapeFile.CheckedIndices)
            {
                DataRow dr = ds_Checked.Tables["Shapefile"].NewRow();
                dr[0] = AttributeColumnsShape.Rows[shapeChecked][0];
                dr[1] = AttributeColumnsShape.Rows[shapeChecked][1];
                dr[2] = AttributeColumnsShape.Rows[shapeChecked][2];
                dr[3] = AttributeColumnsShape.Rows[shapeChecked][3];
                dr[4] = AttributeColumnsShape.Rows[shapeChecked][4];
                dr[5] = AttributeColumnsShape.Rows[shapeChecked][5];
                ds_Checked.Tables["Shapefile"].Rows.Add(dr);
            }

            return ds_Checked.GetXml();

        }

        //###################################################
        //Method must replaced to build datatable from a datatable
        //###################################################
        private void BuildTable()
        {
            foreach (int indexChecked in clbShapeFile.CheckedIndices)
            {
                switch(indexChecked)
                {
                    case 0:
                        dt_dbase.Columns.Add(new DataColumn("ContentLength", System.Type.GetType("System.String")));
                        break;
                    case 1:
                        dt_dbase.Columns.Add(new DataColumn("NumberOfParts", System.Type.GetType("System.String")));
                        break;
                    case 2:
                        dt_dbase.Columns.Add(new DataColumn("NumberOfPoints", System.Type.GetType("System.String")));
                        break;
                    case 3:
                        dt_dbase.Columns.Add(new DataColumn("RecordNumber", System.Type.GetType("System.String")));
                        break;
                    case 4:
                        dt_dbase.Columns.Add(new DataColumn("ShapeType", System.Type.GetType("System.String")));
                        break;
                    case 5:
                        dt_dbase.Columns.Add(new DataColumn("XMax", System.Type.GetType("System.String")));
                        break;
                    case 6:
                        dt_dbase.Columns.Add(new DataColumn("XMin", System.Type.GetType("System.String")));
                        break;
                    case 7:
                        dt_dbase.Columns.Add(new DataColumn("YMax", System.Type.GetType("System.String")));
                        break;
                    case 8:
                        dt_dbase.Columns.Add(new DataColumn("YMin", System.Type.GetType("System.String")));
                        break;
                }    
            }

            for (int i = 0; i < info.ShapeFile.Columns.Count; i++)
            {
                dt_dbase.Columns.Add(new DataColumn(info.ShapeFile.Columns[i].ToString(), System.Type.GetType("System.String")));
            }

            dt_dbase.Columns.Add(new DataColumn("Points", System.Type.GetType("System.String")));

        }

        /// <summary>
        /// Create DataTables and set checked columns
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Load(object sender, EventArgs e)
        {
            SetShapeTable();
            this.clbShapeFile.DataSource = AttributeColumnsShape;
            this.clbShapeFile.DisplayMember = "Name";
            
            foreach (DataRow rowShape in ds_Checked.Tables["Shapefile"].Rows)
            {
                for (int shapeChecked = 0; shapeChecked < clbShapeFile.Items.Count; shapeChecked++)
                {
                    if (AttributeColumnsShape.Rows[shapeChecked][0].ToString().ToUpper() == rowShape[0].ToString().ToUpper())
                    {
                        clbShapeFile.SetItemChecked(shapeChecked, true);
                    }
                }  
            }

            foreach (DataRow rowDbase in ds_Checked.Tables["dbase"].Rows)
            {
                for (int dbaseChecked = 0; dbaseChecked < clbDbaseData.Items.Count; dbaseChecked++)
                {
                    if (AttributeColumns.Rows[dbaseChecked][0].ToString().ToUpper() == rowDbase[0].ToString().ToUpper())
                    {
                        clbDbaseData.SetItemChecked(dbaseChecked, true);
                    }
                }
            }

        }
        
        /// <summary>
        /// Create the Shape Table with Standard Elements
        /// </summary>
        private void SetShapeTable()
        {
            AttributeColumnsShape = new DataTable("ShapeColumns");
            DataColumn col = new DataColumn("Name", System.Type.GetType("System.String"));
            DataColumn colDataType = new DataColumn("DataType", System.Type.GetType("System.String"));
            DataColumn colLength = new DataColumn("Length", System.Type.GetType("System.Int32"));
            DataColumn colPrecision = new DataColumn("Precision", System.Type.GetType("System.Int32"));
            DataColumn colScale = new DataColumn("Scale", System.Type.GetType("System.Int32"));
            DataColumn colCodePage = new DataColumn("CodePage", System.Type.GetType("System.Int32"));

            AttributeColumnsShape.Columns.Add(col);
            AttributeColumnsShape.Columns.Add(colDataType);
            AttributeColumnsShape.Columns.Add(colLength);
            AttributeColumnsShape.Columns.Add(colPrecision);
            AttributeColumnsShape.Columns.Add(colScale);
            AttributeColumnsShape.Columns.Add(colCodePage);
            
            DataRow row = AttributeColumnsShape.NewRow();
            row["Name"] = "ContentLength";
            row["DataType"] = DataType.DT_I4.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "NumberOfParts";
            row["DataType"] = DataType.DT_I4.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "NumberOfPoints";
            row["DataType"] = DataType.DT_I4.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "Points";
            row["DataType"] = DataType.DT_IMAGE.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "RecordNumber";
            row["DataType"] = DataType.DT_I4.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "ShapeType";
            row["DataType"] = DataType.DT_I4.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "XMax";
            row["DataType"] = DataType.DT_R8.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "XMin";
            row["DataType"] = DataType.DT_R8.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "YMax";
            row["DataType"] = DataType.DT_R8.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);

            row = AttributeColumnsShape.NewRow();
            row["Name"] = "YMin";
            row["DataType"] = DataType.DT_R8.ToString();
            row["Length"] = 0;
            row["Precision"] = 0;
            row["Scale"] = 0;
            row["CodePage"] = 0;
            AttributeColumnsShape.Rows.Add(row);
                
        }

        /// <summary>
        /// Open link to codeplex project page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void linkCodeplex_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/j82tPc?r=bb");
        }

        /// <summary>
        /// Open link to datenfabrik GmbH & Co. KG
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void linkDatenfabrik_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/iR6iCD?r=bb");
        }

        /// <summary>
        /// Open link to my blog ssis-components.net
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/aC8F6y?r=bb");
        }

        /// <summary>
        /// Open the ESRI SHP description.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void llESRI_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/kwBJYz?r=bb");
        }

        /// <summary>
        /// Open the shapelib sources
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void linkShapeLib_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/jYbojP?r=bb");
        }

        /// <summary>
        /// Open the ESRI technical description
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/mOWQMZ?r=bb");
        }

        private void rbGeography_CheckedChanged(object sender, EventArgs e)
        {
            lblSRID.Enabled = !rbGeometry.Checked;
            txtSRID.Enabled = !rbGeometry.Checked;
        }

        private void rbGeometry_CheckedChanged(object sender, EventArgs e)
        {
            lblSRID.Enabled = !rbGeometry.Checked;
            txtSRID.Enabled = !rbGeometry.Checked;
        }

        private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bit.ly/f7YdMc?r=bb");
        }

    }
}
